using System;

namespace Dashboard
{
	public abstract class Connection : IDisposable
	{
		private const string CONNECTION_TYPE = "DASHBOARD_CONNECTION_TYPE";

#if WINDOWS		
		private static Type default_type = typeof (TcpConnection);
#else
		private static Type default_type = typeof (DBusConnection);
#endif
		
		private static Type connection_type;
		private static object connection_type_lock = new object (); 

		public abstract void Send (Message message);
		public abstract void Subscribe (string path, MessageHandler handler);
		public virtual void Dispose () { }

		~Connection ()
		{
			Dispose ();
		}

		public static Connection Create ()
		{
			lock (connection_type_lock) {
				if (connection_type == null) {
					string requested = Environment.GetEnvironmentVariable (CONNECTION_TYPE);
					
					if (String.IsNullOrEmpty (requested))
						return Create (default_type);
					
					switch (requested.ToLower ()) {
					case "unix":
						connection_type = typeof (UnixConnection);
						break;

					case "tcp":
						connection_type = typeof (TcpConnection);
						break;

					case "file":
						connection_type = typeof (FileConnection);
						break;

					case "dbus":
						connection_type = typeof (DBusConnection);
						break;

					default:
						try {
							connection_type = Type.GetType (requested);
						} catch (Exception ex) {
							throw new ApplicationException ("Custom connection type", ex);
						}
						break;
					}
				}
			}
			
			return Create (connection_type);
		}

		public static Connection Create (Type type)
		{
			if (type.IsClass && !type.IsAbstract && !type.IsSubclassOf (typeof (Connection)))
				throw new ArgumentException ("Type is a not valid connection");
			
			return Activator.CreateInstance (type) as Connection;
		}
	}
}
